import { useEffect, useMemo, useState } from 'react';
import { Table, Checkbox, message, Form } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { schemaMap } from '@inbiz/render';
import { useOperation, useWorkbench, getMessage } from '@inbiz/react';
import { uuid, getDesignerShowType } from '@inbiz/utils';
import { getPageDetails } from '../../server';
import './style.less';

interface DataType {
    key: string;
    readOnly: string;
    edit: string;
    id: string;
}

export default function FieldWrapper(props: any) {

    return (
        <Form.Item name={['assembly']} className='process-designer-field-form-item'>
            <Field {...props} />
        </Form.Item>
    )
};

function Field(props: any) {
    const { processData, value, onChange } = props;
    const [loading, setLoading] = useState<boolean>(false);
    const [controlResult, setControlResult] = useState<any[]>([]);
    const [control, setControl] = useState<any[]>([]);
    const [editIndeterminate, setEditIndeterminate] = useState(false);
    const [editCheckAll, setEditCheckAll] = useState(false);
    const [requiredIndeterminate, setRequiredIndeterminate] = useState(false);
    const [requiredCheckAll, setRequiredCheckAll] = useState(false);
    const [readOnlyIndeterminate, setReadOnlyIndeterminate] = useState(false);
    const [readOnlyCheckAll, setReadOnlyCheckAll] = useState(false);
    const [hideIndeterminate, setHideIndeterminate] = useState(false);
    const [hideCheckAll, setHideCheckAll] = useState(false);
    let workbench = null;
    let operation = null;
    if (getDesignerShowType() !== 3) {
        workbench = useWorkbench();
        const currentWorkspace = workbench?.activeWorkspace || workbench?.currentWorkspace;
        const currentWorkspaceId = currentWorkspace?.id;
        operation = useOperation(currentWorkspaceId);
    };

    const getAuthority = (authority: string, type: string) => {
        switch (type) {
            case 'edit':
                if (authority?.['x-pattern'] == 'readOnly') {
                    return false;
                } else {
                    return true;
                };
            case 'required':
                return authority?.['required'] || false;
            case 'readOnly':
                if (authority?.['x-pattern'] == 'readOnly') {
                    return true;
                } else {
                    return false;
                };
            case 'hide':
                if (authority?.['x-display'] == 'hidden') {
                    return true;
                } else {
                    return false;
                };
            default:
                return false;
        };
    };

    const initTableData = (controlData: any[]) => {
        setControl(controlData);
        setEditCheckAll(controlData?.every((item) => item?.edit));
        setEditIndeterminate(controlData?.some((item) => item?.edit) && !controlData?.every((item) => item?.edit));
        setRequiredCheckAll(controlData?.every((item) => item?.required));
        setRequiredIndeterminate(controlData?.some((item) => item?.required) && !controlData?.every((item) => item?.required));
        setReadOnlyCheckAll(controlData?.every((item) => item?.readOnly));
        setReadOnlyIndeterminate(controlData?.some((item) => item?.readOnly) && !controlData?.every((item) => item?.readOnly));
        setHideCheckAll(controlData?.every((item) => item?.hide));
        setHideIndeterminate(controlData?.some((item) => item?.hide) && !controlData?.every((item) => item?.hide));
    };

    const synchronizeFormStatus = () => {
        if (controlResult?.length > 0) {
            const controlData = controlResult.map((item) => {
                return {
                    controlId: item?.value,
                    id: 'control' + uuid(20, 60),
                    componentName: getMessage(item.name),
                    edit: getAuthority(item, 'edit'),
                    required: getAuthority(item, 'required'),
                    readOnly: getAuthority(item, 'readOnly'),
                    hide: getAuthority(item, 'hide'),
                };
            });
            initTableData(controlData);
        };
    };

    const echoData = (controlData: any[]) => {
        let _data: any = controlData?.map((item) => {
            let _authority: string[] = [];
            if (item?.edit) {
                _authority.push('edit');
            };
            if (item?.required) {
                _authority.push('required');
            };
            if (item?.readOnly) {
                _authority.push('readOnly');
            };
            if (item?.hide) {
                _authority.push('hide');
            };
            return {
                controlId: item?.controlId,
                authority: _authority.join(','),
            };
        });
        _data = _data?.map((item) => {
            let _authority = {};
            _authority['x-display'] = item?.authority?.indexOf('hide') != -1 ? 'hidden' : 'visible';
            _authority['x-pattern'] = item?.authority?.indexOf('readOnly') != -1 ? 'readOnly' : 'editable';
            _authority['required'] = item?.authority?.indexOf('required') != -1 ? true : false;
            return {
                controlId: item?.controlId,
                ..._authority,
            };
        });
        onChange(_data);
    };

    const onItemChange = (key: string, row: DataType, checked: boolean) => {
        let _control = [...control];
        if (key == 'edit') {
            _control = _control?.map((item) => {
                if (item?.id == row?.id) {
                    return {
                        ...item,
                        edit: true,
                        readOnly: false,
                    };
                } else {
                    return item;
                };
            });
            setEditIndeterminate(!(_control?.every((item) => item?.edit) || _control?.every((item) => !item?.edit)));
            setEditCheckAll(_control?.every((item) => item?.edit));
            setReadOnlyIndeterminate(!(_control?.every((item) => item?.readOnly) || _control?.every((item) => !item?.readOnly)));
            setReadOnlyCheckAll(_control?.every((item) => item?.readOnly));
        } else if (key == 'required') {
            _control = _control?.map((item) => {
                if (item?.id == row?.id) {
                    return {
                        ...item,
                        required: checked,
                    };
                } else {
                    return item;
                };
            });
            setRequiredIndeterminate(!(_control?.every((item) => item?.required) || _control?.every((item) => !item?.required)));
            setRequiredCheckAll(_control?.every((item) => item?.required));
        } else if (key == 'readOnly') {
            _control = _control?.map((item) => {
                if (item?.id == row?.id) {
                    return {
                        ...item,
                        readOnly: true,
                        edit: false,
                    };
                } else {
                    return item;
                };
            });
            setEditIndeterminate(!(_control?.every((item) => item?.edit) || _control?.every((item) => !item?.edit)));
            setEditCheckAll(_control?.every((item) => item?.edit));
            setReadOnlyIndeterminate(!(_control?.every((item) => item?.readOnly) || _control?.every((item) => !item?.readOnly)));
            setReadOnlyCheckAll(_control?.every((item) => item?.readOnly));
        } else if (key == 'hide') {
            _control = _control?.map((item) => {
                if (item?.id == row?.id) {
                    return {
                        ...item,
                        hide: checked,
                    };
                } else {
                    return item;
                };
            });
            setHideIndeterminate(!(_control?.every((item) => item?.hide) || _control?.every((item) => !item?.hide)));
            setHideCheckAll(_control?.every((item) => item?.hide));
        };
        setControl(_control);
        echoData(_control);
    };

    const onAllChange = (key: string, checked: boolean) => {
        let _control = [...control];
        if (key == 'edit') {
            _control = _control?.map((item) => {
                return {
                    ...item,
                    edit: true,
                    readOnly: false,
                }
            });
            setEditIndeterminate(false);
            setEditCheckAll(true);
            setReadOnlyIndeterminate(false);
            setReadOnlyCheckAll(false);
        } else if (key == 'required') {
            _control = _control?.map((item) => {
                return {
                    ...item,
                    required: checked,
                }
            });
            setRequiredIndeterminate(false);
            setRequiredCheckAll(checked);
        } else if (key == 'readOnly') {
            _control = _control?.map((item) => {
                return {
                    ...item,
                    edit: false,
                    readOnly: true,
                }
            });
            setEditIndeterminate(false);
            setEditCheckAll(false);
            setReadOnlyIndeterminate(false);
            setReadOnlyCheckAll(true);
        } else if (key == 'hide') {
            _control = _control?.map((item) => {
                return {
                    ...item,
                    hide: checked,
                }
            });
            setHideIndeterminate(false);
            setHideCheckAll(checked);
        };
        setControl(_control);
        echoData(_control);
    };

    const columns: ColumnsType<DataType> = useMemo(() => {
        return [
            {
                title: '组件名称',
                dataIndex: 'componentName',
                key: 'componentName',
            },
            {
                title: '组件状态',
                children: [
                    {
                        title: <><Checkbox style={{ marginRight: 8 }} indeterminate={editIndeterminate} onChange={(e) => { onAllChange('edit', e.target.checked) }} checked={editCheckAll} />编辑</>,
                        dataIndex: 'edit',
                        key: 'edit',
                        render: (t, r) => {
                            return <Checkbox checked={t} onChange={(e) => { onItemChange('edit', r, e.target.checked) }} />
                        }
                    },
                    {
                        title: <><Checkbox style={{ marginRight: 8 }} indeterminate={readOnlyIndeterminate} onChange={(e) => { onAllChange('readOnly', e.target.checked) }} checked={readOnlyCheckAll} />只读</>,
                        dataIndex: 'readOnly',
                        key: 'readOnly',
                        render: (t, r) => {
                            return <Checkbox checked={t} onChange={(e) => { onItemChange('readOnly', r, e.target.checked) }} />
                        }
                    },
                    {
                        title: <><Checkbox style={{ marginRight: 8 }} indeterminate={hideIndeterminate} onChange={(e) => { onAllChange('hide', e.target.checked) }} checked={hideCheckAll} />隐藏</>,
                        dataIndex: 'hide',
                        key: 'hide',
                        render: (t, r) => {
                            return <Checkbox checked={t} onChange={(e) => { onItemChange('hide', r, e.target.checked) }} />
                        }
                    },
                ]
            },
            {
                title: '校验',
                children: [
                    {
                        title: <><Checkbox style={{ marginRight: 8 }} indeterminate={requiredIndeterminate} onChange={(e) => { onAllChange('required', e.target.checked) }} checked={requiredCheckAll} />必填</>,
                        dataIndex: 'required',
                        key: 'required',
                        render: (t, r) => {
                            return <Checkbox checked={t} onChange={(e) => { onItemChange('required', r, e.target.checked) }} />
                        }
                    },
                ],
            },
        ];
    }, [control, editIndeterminate, requiredIndeterminate, readOnlyIndeterminate, hideIndeterminate, editCheckAll, requiredCheckAll, readOnlyCheckAll, hideCheckAll]);


    useEffect(() => {
        if (processData?.formTypes == 2) {
            const _data = schemaMap(operation.tree, true);
            setControlResult(_data);
        } else {
            if (processData?.processKey) {
                setLoading(true);
                getPageDetails({ ismove: false, processKey: processData?.processKey }).then((res) => {
                    if (res.details?.schema) {
                        let _data = schemaMap(res.details?.schema);
                        if (_data?.length) {
                            setControlResult(_data);
                        };
                    };
                    setLoading(false);
                }).catch((error) => {
                    message.error(error);
                    setLoading(false);
                });
            };
        };
    }, [processData, operation]);

    useEffect(() => {
        if (controlResult?.length > 0) {
            const controlData = controlResult.map((item) => {
                let _authority = value?.find((item1: { controlId: string; }) => item1?.controlId == item?.value);
                return {
                    controlId: item?.value,
                    id: 'control' + uuid(20, 60),
                    componentName: getMessage(item.name),
                    edit: getAuthority(_authority || item, 'edit'),
                    required: getAuthority(_authority || item, 'required'),
                    readOnly: getAuthority(_authority || item, 'readOnly'),
                    hide: getAuthority(_authority || item, 'hide'),
                };
            });
            initTableData(controlData);
        }
    }, [controlResult, value]);

    return (
        <>
            <div style={{ textAlign: 'right', color: 'var(--inbiz-color-primary)', marginBottom: 4 }}>
                <span style={{ cursor: 'pointer' }} onClick={synchronizeFormStatus}>
                    同步表单状态
                </span>
            </div>
            <Table
                columns={columns}
                dataSource={control}
                pagination={false}
                size='small'
                bordered
                loading={loading}
            />
        </>
    )
}